package com.aiex.framework.core.utils;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.aiex.framework.core.base.dto.EnumDTO;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

@Slf4j
public class EnumUtils {

    private EnumUtils() {}

    public static Map<String, List<EnumDTO>> getEnums(String basePackage) throws InvocationTargetException, IllegalAccessException {
        // map 的规则是覆盖，如果存在多个相同的 key 不会报错，因此写一个 set 以验证之
        Set<String> set = new HashSet<>();
        // 扫描该包路径下所有class文件
        Set<Class<?>> classes = ClassUtil.scanPackage(basePackage);
        // 用来存放扫描到的符合要求的【所有枚举】信息，要求参考“ClassUtil.getDeclaredMethod”
        Map<String, List<EnumDTO>> enums = new HashMap<>();
        // 用来存放【当前枚举】的所有属性
        List<EnumDTO> list;
        for (Class<?> aClass : classes) {
            // 判断类是否为枚举类型
            if (ClassUtil.isEnum(aClass)) {
                // 枚举必须有这两个字段，当然也可以根据需求定义更多，将 EnumDto 做相应调整即可！
                Method keyMethod = ClassUtil.getDeclaredMethod(aClass, "getLabel");
                Method valueMethod = ClassUtil.getDeclaredMethod(aClass, "getValue");
                if (keyMethod == null || valueMethod == null) continue;
                // 得到 enum 的所有实例：一个数组，该数组包含组成此 Class 对象表示的枚举类的值，按它们声明的顺序
                Object[] objs = aClass.getEnumConstants();
                // 装载当前枚举所有值
                list = new ArrayList<>();
                for (Object obj : objs){
                    list.add(new EnumDTO((String) keyMethod.invoke(obj), (Integer) valueMethod.invoke(obj)));
                };
                // 装载当前枚举 list 到所有枚举 map
                List<String> parts = StrUtil.split(aClass.getName(), '.');
                // 检查分段数量是否足够
                if (parts.size() < 2) {
                    throw new RuntimeException("包名分段不足2");
                }
                // 直接获取倒数第二个分段
                String enumName = parts.getLast();
                String moduleName = parts.get(parts.size() - 2);
                String key = moduleName + "." + enumName;
                if (!set.add(key)){
                    throw new RuntimeException("同一模块下存在重复枚举名！格式：模块名.枚举名，内容：" + key);
                };
                enums.put(key, list);
            }
        }
        return enums;
    }


}
